#include"soundmanager.h"

const int   INTERFACE_UPDATETIME = 50;      // 50ms update for interface
const float DISTANCEFACTOR = 1.0f;          // Units per meter.  I.e feet would = 3.28.  centimeters would = 100.


soundmanager::soundmanager()
{		
	listenerflag = true;
	listenerpos.x = 0.0f;
	listenerpos.y = 0.0f;
	listenerpos.z = -1.0f * DISTANCEFACTOR;
//	pos.x = 0.0f;
//	pos.y = 0.0f;
//	pos.z = 0.0f;
	channel1 = 0;
	//channel2 = 0;
	//channel3 = 0;
	//channel4 = 0;
	//channel5 = 0;
	dspecho = 0;
}

void soundmanager::ERRCHECK(FMOD_RESULT result)
{
    if (result != FMOD_OK)
	{
        //OGRE_EXCEPT("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
		OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "FMOD error! (" + StringConverter::toString(result) + "): " + FMOD_ErrorString(result), "SoundManager::Initialize");
        //exit(-1);
    }
}

//Create a System object and initialize.
void soundmanager::start(void)
{

    /*
        Create a System object and initialize.
    */
    result = FMOD::System_Create(&system);
    ERRCHECK(result);
    
    result = system->getVersion(&version);
    ERRCHECK(result);

    if (version < FMOD_VERSION)
    {
        
    }
    
    result = system->getDriverCaps(0, &caps, 0, 0, &speakermode);
    ERRCHECK(result);

    result = system->setSpeakerMode(speakermode);       /* Set the user selected speaker mode. */
    ERRCHECK(result);

    if (caps & FMOD_CAPS_HARDWARE_EMULATED)             /* The user has the 'Acceleration' slider set to off!  This is really bad for latency!. */
    {                                                   /* You might want to warn the user about this. */
        result = system->setDSPBufferSize(1024, 10);
        ERRCHECK(result);
    }

    result = system->getDriverInfo(0, name, 256, 0);
    ERRCHECK(result);

    if (strstr(name, "SigmaTel"))   /* Sigmatel sound devices crackle for some reason if the format is PCM 16bit.  PCM floating point output seems to solve it. */
    {
        result = system->setSoftwareFormat(48000, FMOD_SOUND_FORMAT_PCMFLOAT, 0,0, FMOD_DSP_RESAMPLER_LINEAR);
        ERRCHECK(result);
    }

    result = system->init(100, FMOD_INIT_NORMAL, 0);
    if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)         /* Ok, the speaker mode selected isn't supported by this soundcard.  Switch it back to stereo... */
    {
        result = system->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
        ERRCHECK(result);
                
        result = system->init(100, FMOD_INIT_NORMAL, 0);/* ... and re-init. */
        ERRCHECK(result);
    }

    
    /*
        Set the distance units. (meters/feet etc).
    */
    result = system->set3DSettings(1.0, DISTANCEFACTOR, 1.0f);
    ERRCHECK(result);

	//create the echo effect that will be used for explosion of the tank.
	result = system->createDSPByType(FMOD_DSP_TYPE_ECHO, &dspecho);
    ERRCHECK(result);

	result = system->setStreamBufferSize(64*1024, FMOD_TIMEUNIT_RAWBYTES);
    ERRCHECK(result);
}

void soundmanager::loadsound()
{
    /*
        Load some sounds
    */

    result = system->createSound("C:/Users/Mayank/Desktop/sun.mp3", FMOD_SOFTWARE | FMOD_2D, 0, &sound1);
	//result = system->createStream("C:/Users/Mayank/Desktop/sun.mp3", FMOD_OPENONLY, 0, &sound1);
    ERRCHECK(result);
   /* result = sound1->setMode(FMOD_LOOP_OFF);
    ERRCHECK(result);*/
	////burn = 2 /
 //   result = system->createSound("../../media/sounds/bigchargeexplosion.wav", FMOD_SOFTWARE | FMOD_2D, 0, &sound2);
 //   ERRCHECK(result);
 //   result = sound2->setMode(FMOD_LOOP_OFF);
 //   ERRCHECK(result);

 //   result = system->createSound("../../media/sounds/heartmonitorbeep.mp3", FMOD_SOFTWARE | FMOD_2D, 0, &sound3);
 //   ERRCHECK(result);
	//result = sound3->setMode(FMOD_LOOP_OFF);
	//ERRCHECK(result);

	//result = system->createSound("../../media/sounds/crowdcheer6.wav", FMOD_SOFTWARE | FMOD_2D, 0, &sound4);
 //   ERRCHECK(result);
	//result = sound4->setMode(FMOD_LOOP_OFF);
	//ERRCHECK(result);

	////the bullet travelling sound is played in 3D and its sound travels along with the bullet
	//result = system->createSound("../../media/sounds/ExplosionFX02.wav", FMOD_3D, 0, &sound5);
 //   ERRCHECK(result);
	//result = sound2->set3DMinMaxDistance(0.5f * DISTANCEFACTOR, 10.0f * DISTANCEFACTOR);
 //   ERRCHECK(result);
	//result = sound5->setMode(FMOD_LOOP_OFF);
	//ERRCHECK(result);
}

unsigned int soundmanager::timesincestart(void)
{
	unsigned int ms;
    channel1->getPosition(&ms, FMOD_TIMEUNIT_SENTENCE_MS);
	return ms;
}

void soundmanager::play(int soundnum)
{
        //Play sounds at certain positions
	if (soundnum == 1)
	{
			
			result = system->playSound(FMOD_CHANNEL_FREE, sound1, false, &channel1);
			ERRCHECK(result);
			
			
			result = channel1->setPaused(false);
			ERRCHECK(result);

	}
		
	//if (soundnum == 2)
	//{
	//		

	//		result = system->playSound(FMOD_CHANNEL_FREE, sound2, true, &channel2);
	//		ERRCHECK(result);
	//		result = channel2->addDSP(dspecho, 0);
 //           ERRCHECK(result);

 //           result = dspecho->setParameter(FMOD_DSP_ECHO_DELAY, 50.0f);
 //           ERRCHECK(result);
	//		
	//		result = channel2->setPaused(false);
	//		ERRCHECK(result);
	//}
	//if (soundnum == 3)
	//{
	//	result = system->playSound(FMOD_CHANNEL_FREE, sound3, true, &channel3);
	//	ERRCHECK(result);
	//	result = channel3->setPaused(false);
	//	ERRCHECK(result);
	//}
	//if (soundnum == 4)
	//{
	//	result = system->playSound(FMOD_CHANNEL_FREE, sound4, true, &channel4);
	//	ERRCHECK(result);
	//	result = channel4->setPaused(false);
	//	ERRCHECK(result);
	//}
	//if (soundnum == 5)
	//{
	//	result = system->playSound(FMOD_CHANNEL_FREE, sound5, true, &channel5);
	//	ERRCHECK(result);
	//	result = channel5->setPaused(false);
	//	ERRCHECK(result);
	//}
 //   /*
 //       Display help
 //   */
 //   {
 //       int num3d = 0, num2d = 0;

 //       result = system->getHardwareChannels(&num2d, &num3d, 0);
 //       ERRCHECK(result);
 //   }
}

void soundmanager::updatesound(float x, float y, float z)
{
		static float t = 0;
        static FMOD_VECTOR lastpos = { 0.0f, 0.0f, 0.0f };
        FMOD_VECTOR forward        = { 0.0f, 0.0f, 1.0f };
        FMOD_VECTOR up             = { 0.0f, 1.0f, 0.0f };
        FMOD_VECTOR vel;

		listenerpos.x = - x / 10;
		listenerpos.y = - y / 10;
		listenerpos.z = - z / 10;
       

        // ********* NOTE ******* READ NEXT COMMENT!!!!!
        // vel = how far we moved last FRAME (m/f), then time compensate it to SECONDS (m/s).
        vel.x = (listenerpos.x - lastpos.x) * (1000 / INTERFACE_UPDATETIME);
        vel.y = (listenerpos.y - lastpos.y) * (1000 / INTERFACE_UPDATETIME);
        vel.z = (listenerpos.z - lastpos.z) * (1000 / INTERFACE_UPDATETIME);

        // store pos for next time
        lastpos = listenerpos;

        result = system->set3DListenerAttributes(0, &listenerpos, &vel, &forward, &up);
        ERRCHECK(result);

        t += (30 * (1.0f / (float)INTERFACE_UPDATETIME));    // t is just a time value .. it increments in 30m/s steps in this example
        system->update();

}


void soundmanager::shutdown()
{
    /*
        Shut down
    */
    result = sound1->release();
    ERRCHECK(result);
   /* result = sound2->release();
    ERRCHECK(result);
    result = sound3->release();
    ERRCHECK(result);*/

    result = system->close();
    ERRCHECK(result);
    result = system->release();
    ERRCHECK(result);

}
